#ifndef SELECTION_H_
#define SELECTION_H_
#include <stdio.h>
#include <stdlib.h>
#include <memory>
#include <iostream>
#include <string>
#include <time.h>
#include <assert.h>
#include <X11/Xlib.h> 
#include <X11/Xatom.h>
#include "Storage.h"
#include "XWindow.h"
#include "XDisplay.h"

using namespace std;

class Clipboard :SelectionEventListener {
	XWindow *window_;
	Atom clipboard_;
	//auto_ptr<string> last_data;
	ostream& log(string &str) {
		if (this != NULL) {
			return std::cout << endl;	
		}
		return std::cout<< "Clipboard(" << (int)clipboard_ << "):" << str << endl;
	}
	ostream& log() {
		if (this != NULL) {
			return std::cout;	
		}
		//return std::cout<< "Clipboard(" <<(int)clipboard_ <<"):";
	}
	
public:
	Clipboard( XWindow *window, Atom atom):
		window_(window), clipboard_(atom), lastOwnerName() {
		window->getDisplay()->registerHandler(window_->getRawHandler(), static_cast<SelectionEventListener*>(this));
	};
	virtual ~Clipboard() {};
	void printOwner();
	void convert();
	int getAvailable();
	string* getData(int length);
	
	string* getLastData();
	void hijack() {
		window_->takeOverSelection(clipboard_);
	}

	virtual void handleSelectionRequestEvent(XSelectionRequestEvent *req);
	virtual void handleSelectionNotifyEvent(XSelectionEvent *e);
	
	
	
	Window getOwner() {
		return this->window_->getDisplay()->getSelectionOwner(clipboard_);
	}
	
	string lastOwnerName;
	
	string * getOwnerName(const Window owner)  {
		string * name = getWindowName(owner);
		lastOwnerName.assign(*name);
		return name;
	}
	
	string * getOwnerName()  {
		Window owner = getOwner();
		return getOwnerName(owner);
	}
	Atom getAtom() const{
		return clipboard_;
	}
	string * getLastOwnerName() {
		return &lastOwnerName;
	}
	
	void setOwner(Window owner) {
		this->window_->getDisplay()->setSelectionOwner(this->clipboard_, owner);
	}
	
	void setOwner(XWindow *owner) {
		this->window_->getDisplay()->setSelectionOwner(this->clipboard_, owner->getRawHandler());
	}
	
	void convert(Window targetWindow, Atom targetAtom) {
		window_->getDisplay()->convertSelection(clipboard_, targetWindow, targetAtom);
	}
	
	void  setWindowProperty(Window targetWindow, Atom targetProperty, const string& value) { 
		window_->getDisplay()->setWindowProperty(targetWindow, targetProperty, &value);			 
	}
	
	
	string * getWindowName(const Window window) const {
		return window_->getDisplay()->getWindowName(window);
	}		
	
	void handleSelectionClearEvent(XSelectionClearEvent *e);
	


/*
ostream& operator << (ostream& os, XSelection& s){
	Window owner = s.getOwner();
	return os << " window id:" <<  owner <<" name: '" << s.getOwnerName(owner) << "'" << endl;
}
*/


void copyEventFields(XSelectionEvent &target, const XSelectionRequestEvent &source){
	target.display = source.display;
	//target.property = source.property;
	target.requestor = source.requestor;
	target.selection = source.selection;
	//target.send_event = source.send_event;
	//target.serial = source.serial;
	target.target = source.target;
	target.time = source.time;
	//target.type = source.type;
	//respond.xselection.type= SelectionNotify;
	//respond.xselection.display= req->display;
	//respond.xselection.requestor= req->requestor;
	//respond.xselection.selection=req->selection;
	//respond.xselection.target= req->target;
	//respond.xselection.time = req->time;
	
}

private:
	/* dont'allow coping */
	Clipboard(const Clipboard&);
	void operator=(const Clipboard&);
};

#endif /*SELECTION_H_*/
